﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
using System.Text.RegularExpressions;
using AutoFormatter;

namespace AutoFormatter
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public partial class frmMain : System.Windows.Forms.Form
    {

        public frmMain()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();            
            Initialize();

            Icon = Properties.Resources.Application_Icon;
        }

        #region setinfo
        private void SetInfo(string text)
        {
            if (timInfo.Enabled) timInfo.Stop();
            stripStatus.Text = text;
            Application.DoEvents();
        }
        private void SetTempInfo(string text)
        {
            SetInfo(text);
            timInfo.Start();
        }
        private void timInfo_Tick(object sender, System.EventArgs e)
        {
            stripStatus.Text = null;
            timInfo.Stop();
        }
        #endregion

        #region Startup

        /// <summary>
        /// called from the constructor
        /// </summary>
        private void Initialize()
        {
            //Set datasource for comboboxes
            cmbButtonMode.DataSource = Enum.GetValues(typeof(ButtonMode));
            cmbButtonMode.DataBindings.Add("SelectedIndex", AFSettings.Default, "ButtonStyleIndex");
            cmbStartAs.DataSource = AFSettings.Default.BlockModes;
            cmbStartAs.DataBindings.Add("SelectedIndex", AFSettings.Default, "StartAsIndex");
            cmbStyle.DataSource = Enum.GetValues(typeof(BorderStyles));
            cmbStyle.DataBindings.Add("SelectedIndex", AFSettings.Default, "BorderStyleIndex");
            
            txtRealStartAs.DataBindings.Add("Text", AFSettings.Default, "AllowedStartAsString");
            rtb.DataBindings.Add("Rtf", AFSettings.Default, "LastRTF");

            //initialize settings
            initsettings();
            PB.Visible = false;

            //initialize parser
            parser = new AFParser(AFSettings.Default);
            parser.ProgressInterface = PB;
        }

        #endregion

        /// <summary>
        /// The object actually used for parsing
        /// </summary>
        AFParser parser;
        private void Convert(bool force)
        {
            TabC.Focus();
            if (!force && UpToDate) return;

            //Check if there is text to convert
            if (rtb.TextLength == 0)
            {
                txtHTML.Text = null;
                SetTempInfo("No text to convert");
                return;
            }

            try
            {                
                PB.Visible = true;
                txtHTML.Text = parser.GetHTML(rtb);
                txtHTML.Modified = true;
                rtb.Modified = false;
                SetTempInfo("Converting completed succesfully");
                UpToDate = true;     
            }
            catch (Exception ex)
            {
                SetTempInfo("Converting failed");
                MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace);
            }
            finally
            {
                PB.Visible = false;
            }
        }

        #region refresh
        private void refresh(object sender, EventArgs e)
        {
            refresh(true);
        }

        void refresh(bool force)
        {
            Convert(force);
            if (TabC.SelectedTab == tpPreview)
                Preview();
        }
        private void tabC_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            if (TabC.SelectedTab != tpRTF)
                refresh(false);
        }
        #endregion

        #region interface 
        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode >= Keys.F2 && e.KeyCode < Keys.F2 + TabC.TabCount)
                TabC.SelectedIndex = e.KeyCode - Keys.F2;
            else
                base.OnKeyDown(e);
        }

        /// <summary>
        /// Copies the html to the clipboard
        /// </summary>
        private void btnClipBoard_Click(object sender, System.EventArgs e)
        {
            Convert(false);
            Clipboard.SetDataObject(txtHTML.Text, true);
            SetTempInfo("HTML copied to clipboard");
        }

        #endregion

      
        #region control enum
        /*
        public static List<ControlType> GetControls<ControlType>(Control Parent)
    where ControlType : Control
        {

            List<ControlType> coll = new List<ControlType>();
            findControls<ControlType>(coll, Parent);
            return coll;
        }
        public static void findControls<ControlType>(List<ControlType> coll, Control Parent)
            where ControlType : Control
        {
            foreach (Control c in Parent.Controls)
            {
                if (c is ControlType)
                    coll.Add(c as ControlType);
                if (c.HasChildren)
                    findControls(coll, c);
            }
        }
         * */

        List<Control> GetSettingsControls()
        {
            List<Control> List = new List<Control>();
            findControls(List, pnlSettings);
            return List;            
        }
        void findControls(List<Control> coll, Control Parent)
        {
            foreach (Control c in Parent.Controls)
            {
                if (c is Panel)
                    findControls(coll, c);                    
                if (c.HasChildren)
                    coll.Add(c);
            }
        }

        #endregion

        #region Versioning
        int convertversion, settingversion;


        /// <summary>
        /// determines if the currentversion is the same as the version as in the settings
        /// </summary>
        bool UpToDate
        {
            get { return settingversion == convertversion; }
            set
            {
                if (value == UpToDate) return;
                if (!value)
                {
                    settingversion++;
                    SetInfo("Properties changed, press 'Recreate' (or F5) to refresh the HTML");
                }
                else
                    convertversion = settingversion;
                llRefresh.LinkVisited = value;
            }
        }
        #endregion

        #region Preview

        /// <summary>
        /// Creates a file to be shown in the webbrowser
        /// </summary>
        private void Preview()
        {
            Convert(false);
            if (txtHTML.Modified)
            {
                try
                {
                    browser.Document.Body.InnerHtml =
                        AFSettings.Default.TestHTMLBeforeBlock
                        + txtHTML.Text
                        + AFSettings.Default.TestHTMLAfterBlock;
                    txtHTML.Modified = false;
                }
                catch (Exception ex) { MessageBox.Show(ex.Message); }
            }
        }

        #endregion

        #region Save/restore settings

        private void initsettings()
        {
            if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
            {
                AFSettings.Default.PropertyChanged += new PropertyChangedEventHandler(Default_PropertyChanged);
                UpToDate = false;
                Setup();
            }
        }

        /// <summary>
        /// This sub is called when a setting or the text is changed. In other words
        /// when the html code needs to be recreated
        /// </summary>
        void Default_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.UpToDate = false;
            Setup();
        }
        /// <summary>
        /// determines which controls are accessible
        /// </summary>
        private void Setup()
        {
            AFSettings s = AFSettings.Default;
            pnlBlock.Enabled = s.Showblock;
            pnlBorder.Enabled = s.ShowBorder;
            pnlStyle.Enabled = s.ShowSwitchModes;
            grpAllowedModes.Enabled = s.AllowSwitchMode;
        }

        void RtfTextChanged(object sender, EventArgs e)
        {
            this.UpToDate = false;
        }

        private void savesettings()
        {
            AFSettings.Default.Save();
        }
        protected override void OnClosed(EventArgs e)
        {
            savesettings();
            base.OnClosed(e);
        }
        #endregion

        #region advanced (ish) options
        private void btnAdvancedOptions_Click(object sender, EventArgs e)
        {
            ShowAdvancedOptions = !ShowAdvancedOptions;
        }

        bool ShowAdvancedOptions
        {
            get { return pnlAdvancedOptions.Visible; }
            set
            {
                if(value == ShowAdvancedOptions)return;
                showAdvancedoptionsToolStripMenuItem.Checked = value;
                pnlAdvancedOptions.Visible = value;
                btnAdvancedOptions.ReverseArrow = !value;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            ShowAdvancedOptions = false;
        }

        #region EditText
        class TextEditor : Form
        {
            TextBox tb;
            Panel p = new Panel();
            Button btnCancel = new Button(), btnOk = new Button();
            TextBox txtEdit=new TextBox();
            public TextEditor(TextBox tb)
            {
                this.tb = tb;
                txtEdit.Text = tb.Text;
                txtEdit.Modified = false;
                txtEdit.Multiline = true;
                txtEdit.Dock = DockStyle.Fill;
                Controls.Add(txtEdit);

                p.Dock = DockStyle.Bottom;
                p.Height = 30;
                Controls.Add(p);

                btnOk.Text = "OK";
                btnOk.Dock = DockStyle.Right;
                p.Controls.Add(btnOk );
                btnOk.Click += new EventHandler(btnOk_Click);

                btnCancel.Text = "Cancel";
                btnCancel.Dock = DockStyle.Right;
                p.Controls.Add(btnCancel);
                CancelButton = btnCancel;

                StartPosition = FormStartPosition.Manual;
                Point loc = tb.PointToScreen(Point.Empty);
                loc.Y+=tb.Height;
                Location = loc;
            }

            void btnOk_Click(object sender, EventArgs e)
            {
                if (txtEdit.Modified)
                {
                    tb.Text = txtEdit.Text;
                }
                DialogResult = DialogResult.OK;
                Close();
            }
        }
        class TextEditButton:Button
        {
            public TextEditButton()
            {
                base.Text = "...";
            }

            [DefaultValue("...")]
            public override string Text
            {
                get
                {
                    return base.Text;
                }
                set
                {
                    base.Text = value;
                }
            }

            private TextBox tb;

            public TextBox TextBoxToEdit
            {
                get { return tb; }
                set { tb = value; }
            }
            
            protected override void OnClick(EventArgs e)
            {
                new TextEditor(tb).ShowDialog(this);   
            }
        }
        #endregion

        #region FastSettings
        private void btnRestoreSettings_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to restore to the default settings?", "Restore settings", MessageBoxButtons.YesNoCancel)
                == DialogResult.Yes)
                AFSettings.Default.Reset();
        }

        private void btnSetTextOnly_Click(object sender, EventArgs e)
        {
            AFSettings s = AFSettings.Default;
            s.UseBorder = false;
            s.Showblock = false;
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            AFSettings.Default.Reload();
        }
        #endregion

        private void llEditReplacements_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            MessageBox.Show("Sorry, not implemented just yet. Next version coming up");
        }

        #endregion


        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new frmAbout().ShowDialog(this);
        }

        private void llCopy_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Clipboard.SetText(rtb.Rtf);
        }



    }

    #region SwitchModes
    class SwitchModesSelector : FlowLayoutPanel,INotifyPropertyChanged
    {
        class smCheck : CheckBox
        {
            public readonly BlockMode b;
            public smCheck(BlockMode bm)
            {
                b = bm;
                Text = bm.ToString();
                Checked = true;
                Height = 15;
            }

            protected override void OnCheckedChanged(EventArgs e)
            {
                if (Parent != null)
                {
                    (Parent as SwitchModesSelector).onValueChanged();
                }
            }
        }

        public SwitchModesSelector()
        {
            FlowDirection = FlowDirection.TopDown;
            WrapContents = false;
            foreach (BlockMode bm in AFSettings.Default.BlockModes)
            {
                smCheck c = new smCheck(bm);
                Controls.Add(c);
            }
        }

        [DefaultValue(7)]
        [SettingsBindable(true)]
        public int Value
        {
            get
            {
                int i = 0;
                foreach (smCheck c in Controls)
                    if (c.Checked) i += (int)c.b;
                return i;
            }
            set
            {
                foreach (smCheck c in Controls)
                    c.Checked = (value & (int)c.b) > 0;
                onValueChanged();
            }
        }

        void onValueChanged()
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Value"));
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
    #endregion
}

